/*
 * @Author: fuhongliang-TSJ hongliang.fu@4d-bios.com
 * @Date: 2025-10-13 10:58:22
 * @LastEditTime: 2025-10-15 09:00:53
 * @LastEditors: fuhongliang-TSJ hongliang.fu@4d-bios.com
 * @Description: 
 * @FilePath: \lc_-esp32_-s3\main\lc\handheld\game_app.c
 * 立创实战派ESP32-S3开发板
 * Copyright (c) 2025 by 4D Bios, All Rights Reserved. 
 */

#include "handheld.h"
#include "bsp_lvgl.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

static const char *TAG = "game_app";

extern lv_obj_t *icon_in_obj; // 应用界面
extern int icon_flag;

static lv_timer_t *my_lv_timer;

static lv_obj_t *obj_mat;
static lv_obj_t *led_ball;

static int strength = 0;
static int mat_flag;     // 弹力球标志位
static int ball_height = 0; // 弹力球的高度
static int ball_dir = 0; // 弹力球的方向
static int mat_height = 0; // 垫子的高度

/**
 * @description: 返回主界面向上滑动事件处理函数
 * @param {lv_event_t} *e
 * @return {*}
 */
static void my_gesture_event_cb(lv_event_t *e)
{
    lv_dir_t dir = lv_indev_get_gesture_dir(lv_indev_get_act());
    if (dir == LV_DIR_TOP)
    {
        printf("my_gesture_event_cb\n");
        lv_obj_del(icon_in_obj); //删除画布
        lv_timer_del(my_lv_timer);
        icon_flag = 0;
    }
}

/**
 * @description: 计算按下时间和强度事件处理函数
 * @param {lv_event_t} *e
 * @return {*}
 */
static void icon_in_obj_cb(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    
    // 获取当前活动的输入设备及其处理数据
    lv_indev_t * indev = lv_indev_get_act();
    if (indev == NULL) return;
    _lv_indev_proc_t * proc = &indev->proc;

    if(code == LV_EVENT_PRESSING) {
        strength++;
    }
    else if(code == LV_EVENT_RELEASED) {
        // 计算按下持续时间：使用LVGL内部记录的时间戳
        // proc->pr_timestamp 是按下动作发生时LVGL自动记录的时间点
        uint32_t press_duration = lv_tick_elaps(proc->pr_timestamp);
        ESP_LOGI(TAG, "对象按下持续时间: %lu 毫秒", (unsigned long)press_duration);

        // 示例：根据按压时间执行不同逻辑
        if(press_duration > 1000) {
            ESP_LOGD(TAG, "长按操作触发特定功能!");
        } else {
            ESP_LOGD(TAG, "短按操作.");
        }

        strength = 0;
    }

}

/**
 * @description:  定时更新
 * @param {lv_timer_t *} timer
 * @return {*}
 */
static void game_update_cb(lv_timer_t * timer)
{
    if (strength != 0)  // 发现有手指按下屏幕
    {
        if (strength < 31) // 限制手指按下时间最大为30
        {
            mat_height = 60 - strength;   // 计算正方体的高度
            lv_obj_set_size(obj_mat, 80, mat_height);  // 调整正方体的高度
            lv_obj_align_to(led_ball, obj_mat, LV_ALIGN_OUT_TOP_MID, 0, 0);  // 让弹力球跟随垫子一起移动
            mat_flag = 1; // 表示垫子已经缩小过
        }
    }
    else if (mat_flag == 1) // 如果垫子已经缩小过
    {
        lv_obj_set_size(obj_mat, 80, 60); // 垫子回弹到原始值
        lv_obj_align_to(led_ball, obj_mat, LV_ALIGN_OUT_TOP_MID, 0, 0); // 弹力球跟随垫子
        mat_flag = 2; // 标记垫子已经回弹
    }
    else if (mat_flag == 2) // 垫子已经回弹 小球应该向上走了
    {
        if (ball_dir == 0) // 向上运动
        {
            if (ball_height < 150)  // 限制弹力球上弹高度为150像素
            {
                ball_height = ball_height + 10;  // 每次上升10个像素
                lv_obj_align_to(led_ball, obj_mat, LV_ALIGN_OUT_TOP_MID, 0, -ball_height);  // 更新弹力球位置
                if (ball_height >= (0 + (60 -mat_height)*5)) // 根据力度计算小球最大高度
                {
                    ball_dir = 1;  // 如果达到最大高度 更改小球运动方向
                }
            }
        }
        else // 向下运动
        {
            if (ball_height > 0) // 限制小球最低高度
            {
                ball_height = ball_height - 10; // 每次降低10个像素高度
                lv_obj_align_to(led_ball, obj_mat, LV_ALIGN_OUT_TOP_MID, 0, -ball_height); // 更新弹力球高度
                if (ball_height == 0) // 如果弹力球落到了垫子上
                {
                    mat_flag = 0; // 垫子状态恢复
                    ball_dir = 0; // 小球方向恢复
                    mat_height = 0; // 垫子高度恢复
                }
            }
        }
    }
    
}

/**
 * @description: 弹力游戏应用
 * @return {*}
 */
void game_app(void)
{
    mat_flag = 0; // 垫子状态恢复
    ball_dir = 0; // 小球方向恢复
    mat_height = 0; // 垫子高度恢复
    strength = 0;  // 触摸强度恢复
    ball_height = 0; // 弹力球的高度恢复
    
    lvgl_port_lock(0);

    static lv_style_t style;
    lv_style_init(&style);
    lv_style_set_radius(&style, 10);
    lv_style_set_opa(&style, LV_OPA_COVER);
    lv_style_set_bg_color(&style, lv_color_hex(0xcccccc));
    lv_style_set_border_width(&style, 0);
    lv_style_set_pad_all(&style, 0);
    lv_style_set_width(&style, 320);
    lv_style_set_height(&style, 240);
    
    // 创建一个界面
    icon_in_obj = lv_obj_create(lv_scr_act());
    lv_obj_add_style(icon_in_obj, &style, 0);
    
    // 创建一个垫子
    static lv_style_t style_mat;
    lv_style_init(&style_mat);
    lv_style_set_radius(&style_mat, 0);
    lv_style_set_opa(&style_mat, LV_OPA_COVER);
    lv_style_set_bg_color(&style_mat,  lv_color_hex(0x6B8E23));
    lv_style_set_shadow_width(&style_mat, 10);
    lv_style_set_shadow_color(&style_mat, lv_color_black());
    lv_style_set_shadow_ofs_x(&style_mat, 10);
    lv_style_set_shadow_ofs_y(&style_mat, 10);
    lv_style_set_border_width(&style_mat, 0);
    lv_style_set_pad_all(&style_mat, 0);
    lv_style_set_width(&style_mat, 80);
    lv_style_set_height(&style_mat, 60);

    obj_mat = lv_obj_create(icon_in_obj);
    lv_obj_add_style(obj_mat, &style_mat, 0);
    lv_obj_align(obj_mat, LV_ALIGN_BOTTOM_LEFT, 30, -30);

    led_ball = lv_led_create(icon_in_obj);
    lv_led_set_color(led_ball, lv_palette_main(LV_PALETTE_ORANGE));
    lv_led_set_brightness(led_ball, 150);
    lv_obj_align_to(led_ball, obj_mat, LV_ALIGN_OUT_TOP_MID, 0, 0);

    // 返回提示符
    lv_obj_t *label_back = lv_label_create(icon_in_obj);
    lv_label_set_text(label_back, LV_SYMBOL_UP);
    lv_obj_set_style_text_color(label_back, lv_color_hex(0xffffff), 0);
    lv_obj_set_style_text_font(label_back, &lv_font_montserrat_20, 0);
    lv_obj_align(label_back, LV_ALIGN_BOTTOM_RIGHT, -20, -20);

    lvgl_port_unlock();

    // 添加向上滑动退出功能
    lv_obj_add_event_cb(icon_in_obj, my_gesture_event_cb, LV_EVENT_GESTURE, 0);
    lv_obj_clear_flag(icon_in_obj, LV_OBJ_FLAG_GESTURE_BUBBLE);
    lv_obj_add_flag(icon_in_obj, LV_OBJ_FLAG_CLICKABLE);
    
    // 添加计算按下时间强度功能
    lv_obj_add_event_cb(icon_in_obj, icon_in_obj_cb, LV_EVENT_PRESSING, NULL);
    lv_obj_add_event_cb(icon_in_obj, icon_in_obj_cb, LV_EVENT_RELEASED, NULL);

    lv_obj_add_flag(obj_mat, LV_OBJ_FLAG_EVENT_BUBBLE);
    lv_obj_add_event_cb(obj_mat, icon_in_obj_cb, LV_EVENT_PRESSING, NULL);
    lv_obj_add_event_cb(obj_mat, icon_in_obj_cb, LV_EVENT_RELEASED, NULL);

    // 创建一个lv_timer 定时更新数据
    my_lv_timer = lv_timer_create(game_update_cb, 50, NULL);      

    // 标记已经进入第八个应用
    icon_flag = 8;
}